import pandas as pd
import matplotlib.pyplot as plt
import seaborn as sns
from matplotlib import patches
from mpl_toolkits.mplot3d import Axes3D
import numpy as np
from matplotlib.ticker import MaxNLocator
from scipy.interpolate import griddata

sns.set(style="white", font_scale=1.5)
plt.rcParams['font.sans-serif'] = "Simsun"

# 读取Excel文件中所有工作表的数据
excel_file = 'D:\\文档\\DLMU\\实验结果.xlsx'
xls = pd.ExcelFile(excel_file)
dfs = []

# 遍历所有工作表，读取数据并合并
for sheet in xls.sheet_names:
    df = pd.read_excel(excel_file, sheet_name=sheet)
    dfs.append(df)

# 将所有工作表的数据合并为一个DataFrame
data = pd.concat(dfs)

# 去除狮群列为空的行
data = data.dropna(subset=['狮群'])

# 计算每组参数组合的目标函数平均值
grouped = data.groupby(['狮群', '迭代'], as_index=False)['目标函数'].mean()
print(grouped)

# 创建透视表用于绘制热图
pivot_table = grouped.pivot_table(index='狮群', columns='迭代', values='目标函数', aggfunc='mean')
# print(pivot_table)

# 绘制热图
plt.figure(figsize=(12, 8))
# 生成更细的网格
狮群_vals = np.linspace(grouped['狮群'].min(), grouped['狮群'].max(), 101)
迭代_vals = np.linspace(grouped['迭代'].min(), grouped['迭代'].max(), 101)
狮群_grid, 迭代_grid = np.meshgrid(狮群_vals, 迭代_vals)

# sns.heatmap(pivot_table, annot=False, cmap='YlGnBu')

# 对数据进行插值，生成更密集的网格
Z_smooth = griddata((grouped['狮群'], grouped['迭代']), grouped['目标函数'], (狮群_grid, 迭代_grid), method='cubic')

# 找到最小目标函数值的位置
min_value = np.min(Z_smooth)
min_index = np.unravel_index(np.argmin(Z_smooth), Z_smooth.shape)
min_x = 狮群_vals[min_index[1]]
min_y = 迭代_vals[min_index[0]]
print(min_x, min_y, min_value)

# 绘制插值后的平滑热图
ax= sns.heatmap(Z_smooth, cmap='YlGnBu', xticklabels=10, yticklabels=10)

# 标记目标函数最小值的位置
plt.scatter(min_index[1] + 0.5, min_index[0]+ 0.5, color='red', s=10, edgecolor='black', label='Minimum Value')
plt.text(min_index[1]+ 0.5, min_index[0]+ 0.5, f'{min_value:.2f}', color='black', ha='center', va='top', fontsize=10, weight='bold')

# 突出显示目标函数最小值附近的圆形区域
highlight_radius = 10  # 圆的半径
circle = patches.Circle((min_index[1] + 0.5, min_index[0] + 0.5), highlight_radius,
                        linewidth=2, edgecolor='red', facecolor='none', linestyle='--')
ax.add_patch(circle)

# 反转 y 轴
plt.gca().invert_yaxis()

# 设置x轴和y轴的刻度为整数
# plt.gca().xaxis.set_major_locator(MaxNLocator(integer=True))
# plt.gca().yaxis.set_major_locator(MaxNLocator(integer=True))

# plt.title('种群数量与迭代次数对目标函数的影响')
plt.xlabel('种群数量', labelpad=20)
plt.ylabel('迭代次数', labelpad=20)

plt.show()

# 绘制3D响应面图
fig = plt.figure(figsize=(10, 8))
ax = fig.add_subplot(111, projection='3d')

# 创建网格
X, Y = np.meshgrid(sorted(grouped['狮群'].unique()), sorted(grouped['迭代'].unique()))
Z = pivot_table.values
# 生成更细的网格
狮群_vals = np.linspace(grouped['狮群'].min(), grouped['狮群'].max(), 100)
迭代_vals = np.linspace(grouped['迭代'].min(), grouped['迭代'].max(), 100)
狮群_grid, 迭代_grid = np.meshgrid(狮群_vals, 迭代_vals)

# 使用插值函数
Z_smooth_3d = griddata((grouped['狮群'], grouped['迭代']), grouped['目标函数'], (狮群_grid, 迭代_grid), method='cubic')

# 绘制平滑的3D表面图
ax.plot_surface(狮群_grid, 迭代_grid, Z_smooth_3d, cmap='viridis', edgecolor='none')

# 设置x轴和y轴的刻度为整数
# ax.xaxis.set_major_locator(MaxNLocator(integer=True))
# ax.yaxis.set_major_locator(MaxNLocator(integer=True))

ax.set_title('狮群, 迭代与目标函数的响应面图')
ax.set_xlabel('狮群数量', labelpad=20)
ax.set_ylabel('迭代次数', labelpad=30)
ax.set_zlabel('目标函数', labelpad=30)

plt.show()